# -*- encoding: utf-8 -*-

# Copyright 2010 István Szentandrási
# <etude-music-player@googlegroups.com>

# This file is part of Etude.
#
# Etude is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as 
# published by the Free Software Foundation, either version 3 
# of the License, or (at your option) any later version.
#
# Etude is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Etude. If not, see <http://www.gnu.org/licenses/>.

from . import _

import etude.plugins as ep
import etude.client as ec
import etude.img as img
import gtk
import cgi

IMAGE_SIZE = 32

class DefaultStatusIcon(ep.PluginExtra):

    """
    Simple status icon in the system tray
    """
    _short_name = "System tray icon"
    _show_name = _("System tray icon")
    _short_descr = ""
    _version = "0.1"
    _unique = "Default_Systray-0.1" # short name + version is enough, just to identify loaded
    _config = {'minimize_to_tray': '1', 
            'minimize_to_tray_on_start': '0', 
            'remember_minimization': '0',
            'minimize_to_tray_on_minimize': '0'}
    _ui = """
        <ui>
            <popup name="systray_menu">
                <menuitem action="toggle_main" />
                <separator name="smsep1" />
                <menuitem action="prev" />
                <menuitem action="play" />
                <menuitem action="pause" />
                <menuitem action="stop" />
                <menuitem action="next" />
                <separator name="smsep2" />
                <menuitem action="preferences" />
                <menuitem action="about" />
                <separator name="smsep3" />
                <menuitem action="stop_daemon" />
                <menuitem action="quit" />
            </popup>
        </ui>
        """

    #I couldnt find a way how to remove the status icon, 
    #so this plugin should be a singleton
    def __new__(cls, *args, **kw):
        if not hasattr(cls, '_instance'):
            orig = super(DefaultStatusIcon, cls)
            cls._instance = orig.__new__(cls, *args, **kw)
        return cls._instance

    def __init__(self, control):
        self._interfaces = {'tray_icon': self.get_tray_icon }
        
        ep.PluginExtra.__init__(self, control)
        
        if not hasattr(self, '_inited'):
            self._inited = True

            self.client = control.get_client()
            self.icon = gtk.status_icon_new_from_icon_name('etude-tray-icon')
            self.icon.connect('popup-menu', self.on_right_click)
            self.icon.connect('activate', self.on_toggle_main)
            #the new version os the tray supports more features
            try:
                self.icon.connect("scroll-event", self.tray_scroll)
                self.icon.connect('button-press-event', self.tray_button_press)
                self.icon.connect('query-tooltip', self.on_show_tooltip)
                self.icon.set_property('has-tooltip', True)
                self.custom_tooltip = True
            except:
                self.custom_tooltip = False
            
        #already inited
        if not self.custom_tooltip:
            self.bind(control.client, 'e_playback_current_id',
                    self.set_active_tooltip)
            self.bind(control.client, 'e_medialib_entry_changed',
                    self.set_active_tooltip)
        self.bind(control.client, 'e_playback_status', self.on_set_icon_status)
        self.bind(control, 'g_plugin_layout_loaded', self.layout_loaded)
        self.bind(control, 'g_plugin_layout_unloaded', self.layout_unloaded)

        self.icon.set_visible(True)
        self.layout_loaded(None, None)

    def on_set_icon_status(self, widget, status):
        """
        Change the icon while playing and paused
        """
        if status == ec.PB_PLAY:
            self.icon.set_from_icon_name('etude-tray-play')
        elif status == ec.PB_PAUSE:
            self.icon.set_from_icon_name('etude-tray-pause')
        else:
            self.icon.set_from_icon_name('etude-tray-icon')
    
    def on_show_tooltip(self, widget, x, y, keyboard_mode, tooltip, data = None):
        """
        If the platform supports it show a custom a tooltip
        """
        def _on_show_tooltip_pic(value):
            if value != None:
                pb = img.get_pixbuf_from_data(value,
                        size=(IMAGE_SIZE,IMAGE_SIZE))
                tooltip.set_icon(pb)
        nfo = self.client.playback.current_info
        if nfo.has_key('picture_front'):
            self.client.bindata.retrieve(nfo['picture_front'],
                    cb=_on_show_tooltip_pic, fast=True)
        info = nfo.get_custom_info('<smart>|{ ' + _('by') + ' <artist>}{ ' +
                _("from") + ' <album>}')
        info = [cgi.escape(nfo) for nfo in info]
        tooltip.set_markup("<b>"+info[0]+"</b>\n"+info[1])
        return True

    def get_tray_icon(self, data = None):
        """
        interface for tray_icon
        if somebody needed the tray icon for sthing, for example notification
        to point to the tray
        """
        return self.icon

    
    def tray_scroll(self, tray, event, data = None):
        """
        If the platform supports it enable changing volume through scrolling
        """
        if event.direction == gtk.gdk.SCROLL_UP:
            self.client.playback.volume_set_relative(diff = 3, fast=True)
        elif event.direction == gtk.gdk.SCROLL_DOWN:
            self.client.playback.volume_set_relative(diff = -3, fast=True)
        return False

    def tray_button_press(self, tray, event, data = None):
        """If the platform supports it middle click causes playback toggle"""
        if event.button == 2:
            ac = self.control.actions.get_action("playpause")
            if ac:
                ac.activate()
            return True
        return False
    
    def set_active_tooltip(self, widget, song_id):
        """
        If custom tooltips aren't supported, set the standard text tooltip
        """
        try:
            curr_id = self.client.playback.current_info['id']
        except KeyError:
            self.icon.set_tooltip(None)
            return
        if curr_id == song_id:
            info = self.client.playback.current_info.get_custom_info(
                    '<smart>{ '+_('by')+' <artist>}{ '+_("from")+' <album>}')
            self.icon.set_tooltip(info[0])
    
    def on_right_click(self, icon, event_button, event_time):
        """
        show menu on right click
        """
        menu = self.control.uimanager.get_widget("/systray_menu")
        menu.popup(None, None, gtk.status_icon_position_menu, event_button,
                event_time, icon)

    def on_toggle_main(self, source, data=None):
        ac = self.control.actions.get_action("toggle_main")
        ac.activate()

    def layout_loaded(self, control, unique):
        """
        This means new main window, so we should connect to it if 
        the minimize to tray is set
        """
        self.layout_unloaded(control, unique)
        
        if(self.get_config('minimize_to_tray_on_start') == '1'):
            self.control.layout.show_main(False)
        
        mw = self.control.layout.get_main_window()
        self.bind_min(mw)
        self.bind_config(mw)
    
    def bind_min(self, mw):
        minimize = bool(int(self.get_config('minimize_to_tray')))
        if minimize:
            hid = self.bind(mw, 'delete_event', self.minimize)
            self.min_bind = (mw, hid)
    
    def bind_config(self, mw):
        if ((self.get_config('remember_minimization') == '1') or 
                (self.get_config('minimize_to_tray_on_minimize') == '1')):
            self.config_bind = (mw, self.bind(mw, 'window-state-event',
                self.window_state_event_cb))
    
    def window_state_event_cb(self, window, event):
        
        minimize_on_start = 0
        if self.get_config('remember_minimization') == '1':
            if not window.get_property('visible'):
                minimize_on_start = 1
            self.set_config('minimize_to_tray_on_start', str(minimize_on_start))
        
        min_on_min = bool(int(self.get_config('minimize_to_tray_on_minimize')))
        if min_on_min:
            if (event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED and 
                    event.new_window_state & gtk.gdk.WINDOW_STATE_ICONIFIED):
                    self.minimize(window, event)
        return False

    def layout_unloaded(self, control, unique):
        """
        Try unbinding...
        """
        self.unbind_min()
        self.unbind_config()

    def unbind_min(self):
        try:
            mw, hid = self.min_bind
            self.unbind(mw, hid)
        except AttributeError:
            #min_bind doesn't exist
            pass

    def unbind_config(self):
        try:
            mw, hid = self.config_bind
            self.unbind(mw, hid)
        except AttributeError:
            #didn't bind to config event
            pass

    def minimize(self, mw, event, data = None):
        """connect to the delete event of the window - and if set, hide the main
        window instead of closing the application
        """
        self.control.layout.show_main(False)
        return True
    

    def show_prefs(self, source, data=None):
        """show preferences for etude"""
        self.control.show_preferences()

    def main_quit(self, source, data = None):
        self.control.quit()

    def unload(self):
        ep.PluginExtra.unload(self)
        self.icon.set_visible(False)
        
    def show_preferences(self, parent):
        """
        Show preferences for tray icon
        """
        dialog = gtk.MessageDialog( parent,
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                gtk.MESSAGE_OTHER,
                buttons=gtk.BUTTONS_OK_CANCEL
                )
        dialog.set_default_size(300, 200)
        dialog.set_markup("<b>"+_("System tray icon settings")+"</b>")
        table = gtk.Table(rows = 4, columns = 1)
        tbutton = gtk.CheckButton(_("Minimize to tray on close"))
        tbutton.set_active(self.get_config('minimize_to_tray') == '1')
        table.attach(tbutton, 0, 1, 0, 1,
                xoptions = gtk.FILL|gtk.EXPAND, yoptions = 0)
        
        tbutton2 = gtk.CheckButton(_("Minimize to tray on minimize"))
        tbutton2.set_active(
                self.get_config('minimize_to_tray_on_minimize') == '1')
        table.attach(tbutton2, 0, 1, 1, 2,
                xoptions = gtk.FILL|gtk.EXPAND, yoptions = 0)
        
        tbutton3 = gtk.CheckButton(_("Minimize to tray on start"))
        tbutton3.set_active(self.get_config('minimize_to_tray_on_start') == '1')
        table.attach(tbutton3, 0, 1, 2, 3,
                xoptions = gtk.FILL|gtk.EXPAND, yoptions = 0)
        tbutton4 = gtk.CheckButton(_("Remember last state"))
        tbutton4.set_active(self.get_config('remember_minimization') == '1')
        table.attach(tbutton4, 0, 1, 3, 4,
                xoptions = gtk.FILL|gtk.EXPAND, yoptions = 0)

        dialog.vbox.add(table)
        dialog.show_all()
        res = dialog.run()
        if res == gtk.RESPONSE_OK:
            mw = self.control.layout.get_main_window()
            
            minim = str(int(tbutton.get_active()))
            curr_minim = self.get_config('minimize_to_tray')
            if minim != curr_minim:
                if minim:
                    self.bind_min(mw)
                else:
                    self.unbind_min()
                self.set_config('minimize_to_tray', minim)
 
            remmin = str(int(tbutton4.get_active()))
            monm = str(int(tbutton2.get_active()))
            curr_remmin = self.get_config('remember_minimization')
            curr_monm = self.get_config('minimize_to_tray_on_minimize')
            if remmin != curr_remmin or monm != curr_monm:
                self.unbind_config()
                if remmin or monm:
                    self.bind_config(mw)
                self.set_config('remember_minimization', remmin)
                self.set_config('minimize_to_tray_on_minimize', monm)

            if remmin == '0':
                min_on_start = str(int(tbutton3.get_active()))
                self.set_config('minimize_to_tray_on_start', min_on_start)
        dialog.destroy()


